package com.hup.minicontroller.client.view.connected;

import com.hup.minicontroller.client.constant.AppConstant;
import com.hup.minicontroller.client.model.AppConfig;
import com.hup.minicontroller.client.model.AppState;
import com.hup.minicontroller.client.mvp.IClientHandler;
import com.hup.minicontroller.client.mvp.IClientHandler.ClientHandlerList;
import com.hup.minicontroller.client.mvp.IConnectedView;
import com.hup.minicontroller.common.SubThreadHandler;
import com.hup.minicontroller.common.constant.ControlActionConstant.FunctionButton;
import com.hup.minicontroller.common.constant.NetConstant.ConnectType;
import com.hup.minicontroller.common.model.dto.ControlConfigDto;
import com.hup.minicontroller.common.model.dto.FullScreenTouchRequest;
import com.hup.utils.commons.hardware.ScreenUtil;
import com.hup.utils.commons.start.ApplicationContext;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.swing.customView.ImageButton;
import com.hup.utils.swing.frame.BaseFrame;
import com.hup.utils.swing.frame.SingletonWindowHelper;
import com.hup.utils.swing.frame.WindowConfigBinder;
import com.hup.utils.swing.frame.WindowConfigBinder.FrameStateHandler;
import com.hup.utils.swing.model.BaseWindowConfig;
import lombok.extern.log4j.Log4j2;

import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

/**
 * 连接成功后的控制窗口
 *
 * @author hugan
 * @date 2021/5/24
 */
@Log4j2
public class ConnectedFrame extends BaseFrame implements IConnectedView {

    private final Window parent;
    private final AppState appState;
    private final AppConfig appConfig;
    private final ClientHandlerList clientHandlers;
    private final SubThreadHandler subThreadHandler;
    private ConnectedForm form;

    public ConnectedFrame(Window parent) {
        super(AppConstant.APP_TITLE);
        this.parent = parent;
        appState = SpringContext.getBean(AppState.class);
        appConfig = appState.getAppConfig();
        clientHandlers = SpringContext.getBean(ClientHandlerList.class);
        subThreadHandler = SpringContext.getBean(SubThreadHandler.class);
        initView();
        initListener();

        subThreadHandler.execute(new NetSpeedRunner());
        SpringContext.getBean(ApplicationContext.class).putBean(IConnectedView.class, this);
    }

    private void initView() {
        form = new ConnectedForm();
        setContentPane(form.root);
        form.controlConfigPanel.setVisible(false);
        setTitle(appState.getServerName());
        Dimension screenSize = ScreenUtil.getScreenSize();
        setSize(screenSize.width / 2, screenSize.height / 2);
        setLocationRelativeTo(null);

        String lanServerHost = appState.getConnectedType() == ConnectType.LAN ? ", " + appState.getLanServerHost() : "";
        form.screenView.setFullIcon(appState.getAppConfig().isDrawFull());
        form.controlConfigPanel.txtServerInfo.setText(String.format("已连接:%s, %s%s", appState.getServerName(), appState.getConnectedType().desc, lanServerHost));
        onControlConfigChanged();

        appConfig.connectWindowConfig.initFrame(this);
    }

    private void initListener() {
        WindowConfigBinder.bind(this, new FrameStateHandler() {
            @Override
            public BaseWindowConfig getConfig() {
                return appConfig.connectWindowConfig;
            }

            @Override
            public void saveConfig(String desc) {
                log.debug("desc={}", desc);
                appConfig.save();
            }
        });

        form.screenView.setTouchEventCallback((action, xPercent, yPercent) -> doInBackground("发送触摸事件", () -> {
            FullScreenTouchRequest request = new FullScreenTouchRequest(action, xPercent, yPercent);
            clientHandlers.forEach(i -> i.onFullScreenTouch(request));
        }));
        form.touchPadView.setTouchEventCallback((touchPadTouch) -> doInBackground("发送触摸事件", () ->
                clientHandlers.forEach(i -> i.onTouchPadTouch(touchPadTouch))
        ));
        //controlConfigPanel
        form.controlConfigPanel.cbEnableScreen.addActionListener(e -> {
            boolean isChecked = form.controlConfigPanel.cbEnableScreen.isSelected();
            log.info("cbEnableScreen={}", isChecked);
            appState.getControlConfig().setEnableScreen(isChecked);
            onControlConfigChanged();
            doInBackground("修改配置", () -> clientHandlers.forEach(IClientHandler::onControlConfigChanged));
        });
        form.controlConfigPanel.sbFps.setValueChangedListener((value, fromUser) -> {
            if (!fromUser) return;
            log.info("sbFps={}", value);
            appState.getControlConfig().setFps(value);
            doInBackground("修改配置", () -> clientHandlers.forEach(IClientHandler::onControlConfigChanged));
        });
        form.controlConfigPanel.sbScreenSize.setValueChangedListener((value, fromUser) -> {
            if (!fromUser) return;
            log.info("sbScreenSize={}", value);
            appState.getControlConfig().setScreenSize(value);
            doInBackground("修改配置", () -> clientHandlers.forEach(IClientHandler::onControlConfigChanged));
        });
        form.controlConfigPanel.sbScreenQuality.setValueChangedListener((value, fromUser) -> {
            if (!fromUser) return;
            log.info("sbScreenQuality={}", value);
            appState.getControlConfig().setScreenQuality(value);
            doInBackground("修改配置", () -> clientHandlers.forEach(IClientHandler::onControlConfigChanged));
        });
        form.controlConfigPanel.btnDrawFull.addActionListener(e -> {
            boolean full = form.controlConfigPanel.btnDrawFull.isSelected();
            appState.getAppConfig().setDrawFull(full);
            appState.getAppConfig().save();
            form.screenView.setFullIcon(full);
            form.screenView.repaint();
        });
        //按钮
        form.btnTrigger.setActionListener(e -> form.controlConfigPanel.setVisible(!form.controlConfigPanel.isVisible()));
        form.btnBack.setTag(FunctionButton.BACK);
        form.btnHome.setTag(FunctionButton.HOME);
        form.btnApp.setTag(FunctionButton.APP);
        ActionListener btnListener = e -> doInBackground("发送按键", () -> {
            FunctionButton button = (FunctionButton) ((ImageButton) e.getSource()).getTag();
            clientHandlers.forEach(iClientHandler -> iClientHandler.onFunctionButton(button));
        });
        form.btnBack.setActionListener(btnListener);
        form.btnHome.setActionListener(btnListener);
        form.btnApp.setActionListener(btnListener);
    }

    public static void switchVisible(Window parent, boolean isShow) {
        ConnectedFrame frame = SingletonWindowHelper.getWindow(ConnectedFrame.class);
        log.info("isShow={}, hasFrame={}", isShow, frame != null);
        if (isShow && frame == null) {
            parent.setVisible(false);
            new ConnectedFrame(parent).setVisible(true);
        } else if (!isShow && frame != null) {
            frame.dispose();
            frame.parent.setVisible(true);
        }
    }

    @Override
    public void onHidden(boolean dispose) {
        log.info("dispose={}", dispose);
        SpringContext.getBean(ApplicationContext.class).removeBean(IConnectedView.class);
        form.screenView.setBackgroundImage(null);
        if (appState.getConnectedType() != null) {
            //用户手工关闭窗口:需要断开连接
            doInBackground("断开连接", () -> {
                SpringContext.getBean(ClientHandlerList.class).get(appState.getConnectedType()).switchClient(false);
                parent.setVisible(true);
            });
        }
    }

    @Override
    public void onControlConfigChanged() {
        ControlConfigDto controlConfig = appState.getControlConfig();
        form.screenView.setVisible(controlConfig.isEnableScreen());
        if (!controlConfig.isEnableScreen()) form.screenView.setBackgroundImage(null);
        //图像配置
        form.controlConfigPanel.updateState(controlConfig, appState);
        boolean isTouchPad = controlConfig.isEnableControl() && !controlConfig.isEnableScreen();
        //功能控制
        form.btnBack.setVisible(controlConfig.isEnableControl());
        form.btnHome.setVisible(controlConfig.isEnableControl());
        form.btnApp.setVisible(controlConfig.isEnableControl());
        //禁控模式
        form.txtDisableControl.setVisible(!controlConfig.isEnableControl());
        //触控板模式
        form.touchPadView.setVisible(isTouchPad);
    }

    @Override
    public void onScreenData(BufferedImage image) {
        //log.info("image={}", image);
        runOnUiThread("刷新图像", () -> {
            form.screenView.setBackgroundImage(image);
            form.screenView.repaint();
        });
    }

    /**
     * 更新网速功能
     */
    private class NetSpeedRunner implements Runnable {

        @Override
        public void run() {
            if (appState.getConnectedType() == null) return;
            StringBuilder sb = new StringBuilder();
            clientHandlers.forEach(i -> i.getSpeedText(sb));
            form.controlConfigPanel.txtNetSpeed.setText(sb.toString());
            subThreadHandler.schedule(this, 1000);
        }
    }

}
